package cmbchina.util;


import com.jcraft.jsch.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.Charset;
import java.util.*;

/**
 * 脚本工具类
 */
public class FlowScriptRunUtils {

    private static final Logger logger = LoggerFactory.getLogger(FlowScriptRunUtils.class);
    public static Properties appConfig = AppConfig.getInstance().getConfig();
    public static final String JSCH_HOST = appConfig.getProperty("sa.url");
    private static final int JSCH_PORT = Integer.parseInt(appConfig.getProperty("sa.port"));//sa端口
    private static final String USER_NAME = appConfig.getProperty("sa.username");
    private static final String PASSWORD = appConfig.getProperty("sa.password");//密码
    private static final int TIME_OUT = 5000;//超时时间
    private static final String SA_RUN_WAY = appConfig.getProperty("sa.runway");;//

    private String charset = "UTF-8"; //设置编码格式
    private JSch jsch;
    private Session session;
    Channel channel = null;


    /**
     * 连接linux服务器
     * @return
     * @throws com.jcraft.jsch.JSchException
     */
    public boolean connect() throws JSchException {

        jsch = new JSch(); //创建JSch对象
        boolean result = false;

        try{

            session = jsch.getSession(USER_NAME, JSCH_HOST, JSCH_PORT);//根据用户名，主机ip，端口获取一个Session对象
            session.setPassword(PASSWORD); // 设置密码
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);// 为Session对象设置properties
            session.setTimeout(TIME_OUT);//设置连接超时时间
            session.connect();

            result = session.isConnected();

        }catch(Exception e){
            logger.error(e.getMessage(), e);
        }finally{

            if(result){
                logger.debug("Connected successfully to jschHost = " + JSCH_HOST + ",as jschUserName = " + USER_NAME + ",as jschPort = " + JSCH_PORT);
            }else{
                logger.debug("Connected fail to jschHost = " + JSCH_HOST + ",as jschUserName = " + USER_NAME + ",as jschPort = " + JSCH_PORT);
            }

        }

        return result;

    }

    /**
     * 关闭连接
     */
    public void close() {

        if(channel != null && channel.isConnected()){
            channel.disconnect();
            channel=null;
        }

        if(session!=null && session.isConnected()){
            session.disconnect();
            session=null;
        }

    }

    /**
     * 执行脚本
     * @param script
     * @param params
     * @return
     */
    public ScriptResult runScript(String script,Map<String,String> params)throws Exception{

        if(params != null && params.size() != 0) {
            for(Map.Entry<String,String> obj:params.entrySet()) {
                script = script.replaceAll("#"+obj.getKey()+"#",obj.getValue());
            }
        }

        return runScript(script);

    }

    /**
     * 执行脚本 -当前用的方法
     * @param command
     * @return
     * @throws Exception
     */
    public ScriptResult runScript(String command) throws Exception{

        logger.debug("执行脚本为:"+command);

        try{

            ScriptResult scriptResult = null;

            if("dashboard".equals(SA_RUN_WAY)) {

                scriptResult =  runScriptByKb(command);

            }else{


                boolean connectResult = connect();

                if(connectResult) {

                    scriptResult = runScriptByJsch(command);
                    scriptResult.setConnect(true);

                }else{
                    scriptResult.setConnect(false);
                }

                close();

            }
            logger.debug("脚本结果为"+scriptResult.toString());
            //设置所有结果都为成功
//       scriptResult.setReturnCode(0);
            return scriptResult;
        }catch (Exception e){
            ScriptResult scriptResult = new ScriptResult();
            scriptResult.setResult(e.getMessage());
            scriptResult.setReturnCode(400);
            return scriptResult;
        }


    }

    /**
     * 用jsch执行脚本
     * @return
     */
    private ScriptResult runScriptByJsch(String command) {

        ScriptResult scriptResult  = new ScriptResult();

        List<String> resultList = new ArrayList<String>();
        BufferedReader reader = null;
        BufferedReader errorReader = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        String res="";

        try {

            channel = session.openChannel("exec");
            ((ChannelExec) channel).setCommand(command);
            channel.setInputStream(null);
            ((ChannelExec) channel).setErrStream(bos);
            channel.connect();
            InputStream in = channel.getInputStream();
            int returnCode  = channel.getExitStatus();
            reader = new BufferedReader(new InputStreamReader(in, Charset.forName(charset)));

            while((res=reader.readLine()) != null) {

                resultList.add(res.replaceAll("\t","\n"));

                if(-1 == returnCode &&(res.indexOf("[Error]") != -1 || res.indexOf("[ERROR]")>=0)) {
                    returnCode = 1;
                }

            }

            if(-1 == returnCode){
                returnCode = 0;
            }

            errorReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bos.toByteArray()),Charset.forName(charset)));
            while((res=errorReader.readLine()) != null)
            {
                resultList.add(res.replaceAll("\t","\n"));
                logger.info(res);
            }


            StringBuffer sb = new StringBuffer();
            for(String result:resultList) {
                sb.append(result);
                sb.append("<br>");
            }

            scriptResult.setReturnCode(returnCode);
            scriptResult.setResult(sb.toString());
            scriptResult.setResultList(resultList);

        } catch (IOException e) {

            logger.error(e.getMessage(),e);

        } catch (JSchException e) {

            logger.error(e.getMessage(), e);

        } finally {

            try {
                reader.close();
                errorReader.close();
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }

        }
        //设置为成功
//        scriptResult.setReturnCode(0);
        return scriptResult;

    }

    /**
     * 用看板接口执行脚本
     * @return
     */
    private ScriptResult runScriptByKb(String command) throws Exception{


        ScriptResult scriptResult = new ScriptResult();

        Map<String,Object> mapScriptParams = new HashMap<String, Object>();
        mapScriptParams.put("shellName",command);
        mapScriptParams.put("shellParam","");
        mapScriptParams.put("hostNames","");
        mapScriptParams.put("userName","");

        String jsonParams = JacksonUitl.getObjectMapper().writeValueAsString(mapScriptParams);

        int returnCode = -2;

        try {

            Map<String,Object> scriptResultMap = ScriptRequestUtil.httpRequestPost(jsonParams);
            if(scriptResultMap.get("returnCode") !=null && !"".equals(scriptResultMap.get("returnCode").toString())) {
                returnCode = Integer.valueOf(scriptResultMap.get("returnCode").toString());
            }

            StringBuffer sb = new StringBuffer();
            List<String> resultList = (List<String>)scriptResultMap.get("outPut");
            for(String result:resultList) {

                if(-1 == returnCode && result.indexOf("[Error]") !=  -1) {
                    returnCode = 1;
                }

                sb.append(result);
                sb.append("<br>");
            }

            if(-1 == returnCode){
                returnCode = 0;
            }

            scriptResult.setReturnCode(returnCode);
            scriptResult.setResult(sb.toString());
            scriptResult.setResultList(resultList);

        }catch (Exception e) {
            scriptResult.setReturnCode(400);
            scriptResult.setResult("================sa或者看板链接不上===================");
            scriptResult.setResultList(new ArrayList<String>());
            e.printStackTrace();
        }

        return scriptResult;

    }

}

